package com.niiwoo.civet.account.service.local.trade;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.account.dao.entity.TransFreezeOrder;
import com.niiwoo.civet.account.dao.entity.TransFreezeOrderExample;
import com.niiwoo.civet.account.dao.mapper.TransFreezeOrderMapperExt;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.enums.AccountAmountTypeEnum;
import com.niiwoo.civet.account.enums.OrderTypeEnum;
import com.niiwoo.civet.account.enums.TransFreezeStatusEnum;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.base.enums.CommonResultEnum;
import com.niiwoo.civet.trade.constant.MqConstant;
import com.niiwoo.civet.trade.dto.common.RefundFreezeResultMsgDTO;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 交易冻结本地服务类
 * Created by wangjichao on 2018/4/23.
 */
@Service
@Slf4j
public class TransFreezeLocalService {
    @Autowired
    private TransFreezeOrderMapperExt transFreezeOrderMapperExt;

    @Autowired
    private AccountBalanceLocalService accountBalanceLocalService;

    @Autowired
    private BillFacade billFacade;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;

    /**
     * 初始化交易冻结订单
     * @param transFreezeOrder
     */
    @Transactional
    public Integer insertTransFreezeOrder(TransFreezeOrder transFreezeOrder){
        return transFreezeOrderMapperExt.insertSelective(transFreezeOrder);
    }

    /**
     * 根据主键查询冻结订单
     * @param id
     * @return
     */
    @Transactional
    public TransFreezeOrder queryTransFreezeOrderById(Long id){
        return transFreezeOrderMapperExt.selectByPrimaryKey(id);
    }


    @Transactional
    public TransFreezeOrder queryTransFreezeOrderByFreezeRequestNo(String freezeRequestNo){
        TransFreezeOrderExample example = new TransFreezeOrderExample();
        TransFreezeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andRequestNoEqualTo(freezeRequestNo);
        List<TransFreezeOrder> transFreezeOrders = transFreezeOrderMapperExt.selectByExample(example);
        if(transFreezeOrders == null || transFreezeOrders.isEmpty()){
            return null;
        }
        return transFreezeOrders.get(0);
    }

    @Transactional
    public TransFreezeOrder queryTransFreezeOrderByIdAndType(Long orderId,OrderTypeEnum orderTypeEnum){
        TransFreezeOrderExample example = new TransFreezeOrderExample();
        TransFreezeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andOrderIdEqualTo(orderId);
        criteria.andOrderTypeEqualTo(orderTypeEnum.getCode());
        List<TransFreezeOrder> transFreezeOrders = transFreezeOrderMapperExt.selectByExample(example);
        if(transFreezeOrders == null || transFreezeOrders.isEmpty()){
            return null;
        }
        return transFreezeOrders.get(0);
    }



    /**
     * 冻结成功
     * @param id
     */
    @Transactional
    public void freezeSuccess(Long id, AddBillAndChangeBalanceDTO addBillAndChangeBalanceDTO){
        Date now = new Date();
        TransFreezeOrder transFreezeOrder = transFreezeOrderMapperExt.selectByPrimaryKeyForUpdate(id);
        //如果状态非处理中，直接幂等返回
        if(!TransFreezeStatusEnum.HANDLING.getValue().equals(transFreezeOrder.getStatus())){
            return;
        }
        //更新订单状态
        TransFreezeOrder updateTransFreezeOrder = new TransFreezeOrder();
        updateTransFreezeOrder.setId(id);
        updateTransFreezeOrder.setStatus(TransFreezeStatusEnum.SUCCESS.getValue());
        updateTransFreezeOrder.setTransactionTime(now);
        updateTransFreezeOrder.setUpdateTime(now);
        transFreezeOrderMapperExt.updateByPrimaryKeySelective(updateTransFreezeOrder);

        //记账，余额
        billFacade.addBillAndChangeBalance(addBillAndChangeBalanceDTO);

        //维护还款冻结金额
        this.freezeSuccessMoneyTotalProcess(transFreezeOrder);

        //事务提交之后发送冻结成功消息
        sendTransFreezeResultMQMsg(transFreezeOrder,CommonResultEnum.SUCCESS);
    }

    /**
     * 冻结失败
     * @param id
     * @param errorCode
     * @param errorMessage
     */

    @Transactional
    public void freezeFailure(Long id,String errorCode,String errorMessage){
        Date now = new Date();
        TransFreezeOrder transFreezeOrder = transFreezeOrderMapperExt.selectByPrimaryKeyForUpdate(id);
        //如果状态非处理中，直接幂等返回
        if(!TransFreezeStatusEnum.HANDLING.getValue().equals(transFreezeOrder.getStatus())){
            return;
        }
        //更新订单状态
        TransFreezeOrder updateTransFreezeOrder = new TransFreezeOrder();
        updateTransFreezeOrder.setId(id);
        updateTransFreezeOrder.setStatus(TransFreezeStatusEnum.FAIL.getValue());
        updateTransFreezeOrder.setErrorCode(errorCode);
        updateTransFreezeOrder.setErrorMessage(errorMessage);
        updateTransFreezeOrder.setUpdateTime(now);
        transFreezeOrderMapperExt.updateByPrimaryKeySelective(updateTransFreezeOrder);

        //事务提交之后发送冻结失败消息
        transFreezeOrder.setErrorCode(errorCode);
        transFreezeOrder.setErrorMessage(errorMessage);
        sendTransFreezeResultMQMsg(transFreezeOrder,CommonResultEnum.FAILURE);
    }


    /**
     * 冻结成功冻结金额维护
     * @param transFreezeOrder
     */
    private void freezeSuccessMoneyTotalProcess(TransFreezeOrder transFreezeOrder){
        OrderTypeEnum orderTypeEnum = OrderTypeEnum.enumOf(transFreezeOrder.getOrderType());
        //仅还款时维护
        if(OrderTypeEnum.REPAYMENT.getCode().equals(transFreezeOrder.getOrderType())){
            List<MoneyTotalDTO> moneyTotalDTOs = new ArrayList<>();
            MoneyTotalDTO refund = new MoneyTotalDTO();
            refund.setAccountId(transFreezeOrder.getAccountId());
            refund.setUserId(transFreezeOrder.getUserId());
            refund.setAmount(transFreezeOrder.getAmount());
            refund.setAmountType(AccountAmountTypeEnum.REPAYMENT_FREEZE);
            moneyTotalDTOs.add(refund);
            //统计金额更新
            moneyTotalLocalService.moneyTotal(moneyTotalDTOs);
        }

    }


    /**
     * 发送交易冻结结果
     * @param transFreezeOrder
     * @param commonResultEnum
     */
    private void sendTransFreezeResultMQMsg(TransFreezeOrder transFreezeOrder,CommonResultEnum commonResultEnum){
        //还款/垫付
        if(OrderTypeEnum.REPAYMENT.getCode().equals(transFreezeOrder.getOrderType())
                || OrderTypeEnum.GUARANTEE.getCode().equals(transFreezeOrder.getOrderType())){
            this.sendRefundFreezeResultMsg(transFreezeOrder,commonResultEnum);
        }
    }

    /**
     * 还款冻结结果发送
     * @param transFreezeOrder
     * @param commonResultEnum
     */
    private void sendRefundFreezeResultMsg(TransFreezeOrder transFreezeOrder,CommonResultEnum commonResultEnum){
        RefundFreezeResultMsgDTO refundFreezeResultMsgDTO = new RefundFreezeResultMsgDTO();
        refundFreezeResultMsgDTO.setOrderId(transFreezeOrder.getOrderId());
        refundFreezeResultMsgDTO.setAmount(transFreezeOrder.getAmount());
        refundFreezeResultMsgDTO.setFreezeRequestNo(transFreezeOrder.getRequestNo());
        refundFreezeResultMsgDTO.setFreezeResult(commonResultEnum);
        refundFreezeResultMsgDTO.setErrorCode(transFreezeOrder.getErrorCode());
        refundFreezeResultMsgDTO.setErrorMessage(transFreezeOrder.getErrorMessage());
        log.info("准备发送交易冻结结果MQ消息:{}", JSON.toJSONString(refundFreezeResultMsgDTO));
        rabbitTemplate.convertAndSend(MqConstant.REFUND_FREEZE_RESULT_EXCHANGE,MqConstant.REFUND_FREEZE_RESULT_ROUTING,refundFreezeResultMsgDTO);
    }

    /**
     * 冻结补单JOB查询数据
     * @return
     */
    public List<TransFreezeOrder> listOrdersForFreezeCheckJob(){
        TransFreezeOrderExample example = new TransFreezeOrderExample();
        TransFreezeOrderExample.Criteria criteria = example.createCriteria();
        criteria.andStatusEqualTo(TransFreezeStatusEnum.HANDLING.getValue());//状态为处理中
        criteria.andCreateTimeLessThan(new DateTime(new Date()).minusMinutes(5).toDate());//不包括最近5分钟创建的
        criteria.andUpdateTimeGreaterThan(new DateTime(new Date()).minusDays(2).toDate());//最多扫描范围两天
        List<TransFreezeOrder> transFreezeOrders = transFreezeOrderMapperExt.selectByExample(example);
        return transFreezeOrders;
    }
}
